package vis.core.service.sys.impl;


import vis.core.common.cache.Cache;
import vis.core.common.security.AuthKit;
import vis.core.common.security.AuthUser;
import vis.core.common.util.IdKit;
import vis.core.common.util.StringKit;
import vis.core.common.util.password.PwdKit;
import vis.core.common.valid.Enum;
import vis.core.common.valid.*;
import vis.core.common.valid.base.Valid;
import vis.core.domain.db.SysRole;
import vis.core.domain.db.SysUser;
import vis.core.domain.db.SysUserRole;
import vis.core.domain.search.Psh;
import vis.core.domain.sys.MSG;
import vis.core.domain.sys.ServiceException;
import vis.core.domain.sys.UserTokenVo;
import vis.core.mapper.SysRoleMapper;
import vis.core.mapper.SysUserMapper;
import vis.core.mapper.SysUserOrgMapper;
import vis.core.mapper.SysUserRoleMapper;
import vis.core.service.sys.SysDictService;
import vis.core.service.sys.SysUserService;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static vis.core.domain.db.table.SysUserTableDef.SYS_USER;

/**
 * 用户表实现
 */
@Slf4j
@Service
public class SysUserServiceImpl implements SysUserService {
    @Resource
    private Cache<String> cache;

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private SysUserRoleMapper sysUserRoleMapper;

    @Resource
    private SysUserOrgMapper sysUserOrgMapper;

    @Resource
    private SysRoleMapper sysRoleMapper;

    @Resource
    private SysDictService dictService;

    @Resource
    private SysUserRoleMapper userRoleMapper;


    @Override
    public UserTokenVo refreshToken(String refreshToken) {
        try {
//            TODO
            return null;
        }
        //刷新Token过期，强制重新登录
        catch (Exception e) {
            throw new ServiceException(MSG.ER_411);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insert(SysUser param) {
        String nickName = param.getNickName();
        String account = param.getAccount();
        String phone = param.getPhone();
        ArrayList<String> roleIdList = StringKit.split(param.getRoleIds());

        //|| StringKit.isBlank(phone)
        if (StringKit.isBlank(nickName) || StringKit.isBlank(account) || roleIdList.isEmpty())
            throw new ServiceException(MSG.PARAM_ER);

        QueryWrapper wrapper = QueryWrapper.create().where(SYS_USER.ACCOUNT.eq(account));
        SysUser queryUser = sysUserMapper.selectOneByQuery(wrapper);
        if (queryUser != null) throw new ServiceException(MSG.ACCOUNT_EXISTS);

        if (StringKit.isNotBlank(phone)) {
            wrapper = QueryWrapper.create().where(SYS_USER.PHONE.eq(phone));
            queryUser = sysUserMapper.selectOneByQuery(wrapper);
            if (queryUser != null) throw new ServiceException(MSG.PHONE_EXISTS);
        }

        //插入用户信息
        SysUser sysUser = new SysUser();
        sysUser.setId(IdKit.getId());
        sysUser.setAccount(account);
        sysUser.setNickName(nickName);
        sysUser.setPhone(phone);
        sysUserMapper.insertSelective(sysUser);

        //插入用户角色信息
        insertUserRole(sysUser.getId(), param.getRoleIds());

        return true;
    }

    @Override
    public boolean delete(String ids) {

        ArrayList<String> split = StringKit.split(ids);

        int i = sysUserMapper.deleteBatchByIds(split);

        return true;
    }

    @Override
    public SysUser appUserInfo() {
        String userId = AuthKit.getCurrentUser().getUserId();
        SysUser sysUser = sysUserMapper.selectOneById(userId);
        if (sysUser != null) {
            sysUser.setPassword("");
        }
        return sysUser;
    }

    @Override
    public SysUser systemUserInfo() {
        AuthUser authUser = AuthKit.getCurrentUser();
        String userId = authUser.getUserId();
        SysUser sysUser = sysUserMapper.selectOneById(userId);
        if (sysUser != null) {
            sysUser.setPassword("");
            setUserRole(sysUser);
            sysUser.setRoot(authUser.getIsRoot());
        }
        return sysUser;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean update(SysUser param) {
        String id = param.getId();
        String nickName = param.getNickName();
        String phone = param.getPhone();
        ArrayList<String> roleIdList = StringKit.split(param.getRoleIds());

        if (StringKit.isBlank(id) || StringKit.isBlank(nickName) || StringKit.isBlank(phone) || roleIdList.size() == 0)
            throw new ServiceException(MSG.PARAM_ER);

        QueryWrapper wrapper = QueryWrapper.create().from(SYS_USER).where(SYS_USER.PHONE.eq(phone)).and(SYS_USER.ID.ne(id));
        if (sysUserMapper.selectOneByQuery(wrapper) != null) throw new ServiceException(MSG.PHONE_EXISTS);

        //更新用户信息
        SysUser sysUser = new SysUser();
        sysUser.setId(id);
        sysUser.setNickName(nickName);
        sysUser.setPhone(phone);
        sysUser.setIsDisable(param.getIsDisable());
        sysUserMapper.update(sysUser);

        //删除用户角色
        userRoleMapper.deleteByQuery(QueryWrapper.create().where("user_id = ?", id));

        //插入用户角色
        insertUserRole(id, param.getRoleIds());

        return true;
    }

    @Override
    public void insertUserRole(String userId, String roleIds) {
        ArrayList<String> roleIdList = StringKit.split(roleIds);

        ArrayList<SysUserRole> userRoles = new ArrayList<>();
        for (String roleId : roleIdList) {
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setUserId(userId);
            sysUserRole.setRoleId(roleId);
            userRoles.add(sysUserRole);
        }
        userRoleMapper.insertBatch(userRoles);
    }

    @Override
    public Page<SysUser> page(SysUser param, Psh psh) {
        QueryWrapper wrapper = QueryWrapper.create().select("*").from(SysUser.class).where(SYS_USER.ACCOUNT.like(param.getAccount())).and(SYS_USER.NICK_NAME.like(param.getNickName())).and(SYS_USER.PHONE.like(param.getPhone())).and(SYS_USER.IS_DISABLE.eq(param.getIsDisable())).and(SYS_USER.ID_CARD_NAME.like(param.getIdCardName())).and(SYS_USER.ID_CARD_NUMBER.like(param.getIdCardNumber())).orderBy(SYS_USER.CT.desc());

        Page<SysUser> page = sysUserMapper.paginate(psh.getPageNumber(), psh.getPageSize(), wrapper);
        List<SysUser> records = page.getRecords();
        for (SysUser sysUser : records) {
            sysUser.setPassword("");
            setUserRole(sysUser);
        }
        return page;
    }

    @Valid
    @Override
    public boolean sysUserRegister(@Enum({"1", "2"}) String type, String phone, String email, @NotBlank String password, @NotBlank String password2, @Length(mast = 6, msg = "验证码输入错误") String captcha) {
        if (!password.equals(password2)) throw new ServiceException(MSG.USER_PASSWORD_2);
        if ("1".equals(type) && !ValidKit.phone.check(phone)) throw new ServiceException(MSG.USER_PHONE_ERROR);
        if ("2".equals(type) && !ValidKit.email.check(email)) throw new ServiceException(MSG.USER_EMAIL_ERROR);

        //查询是否已注册
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.select("id").from(SysUser.class);
        if ("1".equals(type)) wrapper.where(SYS_USER.PHONE.eq(phone));
        if ("2".equals(type)) wrapper.where(SYS_USER.EMAIL.eq(email));
        SysUser userInfo = sysUserMapper.selectOneByQuery(wrapper);
        if (userInfo != null) throw new ServiceException(MSG.USER_LOGIN_IS_REGISTER);

        //插入用户
        String nickName = "1".equals(type) ? phone : email;
        String userPwd = PwdKit.createPwdByPlain(password);
        String id = IdKit.getId();
        SysUser sysUser = new SysUser();
        sysUser.setId(id);
        sysUser.setAccount(id);
        sysUser.setPassword(userPwd);
        sysUser.setNickName(nickName);
        if ("1".equals(type)) sysUser.setPhone(phone);
        if ("2".equals(type)) sysUser.setEmail(email);

        int insert1 = sysUserMapper.insertSelective(sysUser);

        //插入用户角色
        insertUserRole(id, "30");

        return true;
    }

    private void setUserRole(SysUser sysUser) {
        List<String> roleIds = userRoleMapper.selectObjectListByQueryAs(QueryWrapper.create().select("role_id").where("user_id = ?", sysUser.getId()), String.class);
        sysUser.setRoleIds(StringKit.join(roleIds, ","));
        if (roleIds.size() > 0) {
            List<SysRole> sysRoles = sysRoleMapper.selectListByIds(roleIds);
            List<String> names = sysRoles.stream().map(SysRole::getName).collect(Collectors.toList());
            sysUser.setRoleNames(StringKit.join(names, ","));
        }
    }

    @Override
    public boolean resetUserPassword(String userIds, String newPassword) {
        ArrayList<String> userIdList = StringKit.split(userIds);

        for (String userId : userIdList) {
            SysUser sysUser = new SysUser();
            sysUser.setId(userId);
            sysUser.setPassword(PwdKit.createPwdByPlain(newPassword));
            sysUserMapper.update(sysUser);
        }

        return true;
    }

    @Override
    public boolean resetMyPassword(String oldPassword, String newPassword) {
        AuthUser authUser = AuthKit.getCurrentUser();
        String userId = authUser.getUserId();

        //查询用户信息,比对旧密码
        QueryWrapper wrapper = new QueryWrapper().select(SYS_USER.PASSWORD).from(SYS_USER).where(SYS_USER.ID.eq(userId));
        SysUser userInfo = sysUserMapper.selectOneByQuery(wrapper);
        if (!PwdKit.checkPlainPwd(oldPassword, userInfo.getPassword())) {
            throw new ServiceException(MSG.USER_OLD_PASSWORD_ERROR);
        }

        SysUser sysUser = new SysUser();
        sysUser.setId(userId);
        sysUser.setPassword(PwdKit.createPwdByPlain(newPassword));
        sysUserMapper.update(sysUser);

        return true;
    }

    @Override
    public AuthUser createUserTokenExtra(String userId) {
        //用户信息
        SysUser userInfo = sysUserMapper.selectOneById(userId);
        if (userInfo == null) throw new ServiceException(MSG.USER_NOT_FOUND);

        //角色ID
        QueryWrapper roleWrapper = QueryWrapper.create().select("role_id").from("sys_user_role").where("user_id =?", userId);
        List<String> roleIds = sysUserRoleMapper.selectObjectListByQueryAs(roleWrapper, String.class);

        //组织机构ID
        QueryWrapper orgWrapper = QueryWrapper.create().select("org_id").from("sys_user_org").where("user_id =?", userId);
        List<String> orgIds = sysUserOrgMapper.selectObjectListByQueryAs(orgWrapper, String.class);

        //Token携带信息
        AuthUser authUser = new AuthUser();
        authUser.setAccount(userInfo.getAccount());
        authUser.setUserId(userInfo.getId());
        authUser.setRoleIds(roleIds);
        authUser.setOrgIds(orgIds);
        authUser.setIsRoot(roleIds.contains("1"));//角色1是ROOT用户

        return authUser;
    }


    @Override
    public SysUser updateUserInfo(SysUser param) {
        sysUserMapper.update(param);
        return appUserInfo();
    }

    @Override
    public boolean isBindCard() {
        AuthUser authUser = AuthKit.getCurrentUser();

        String userId = authUser.getUserId();
        SysUser sysUser = sysUserMapper.selectOneById(userId);

        return !StringKit.isBlank(sysUser.getIdCardNumber()) && !"0".equals(sysUser.getIdCardNumber());
    }

    @Valid
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean bindCard(@IdCardName String idCardName, @IdCardNumber String idCardNumber) {
        //        RegularKit.id_card_name.check(idCardName, MSG.USER_ID_CARD_NAME);
        //        RegularKit.id_card_number.check(idCardNumber, "身份证号输入错误");

        AuthUser authUser = AuthKit.getCurrentUser();

        String userId = authUser.getUserId();
        SysUser sysUser = sysUserMapper.selectOneById(userId);
        sysUser.setIdCardName(idCardName);
        sysUser.setIdCardNumber(idCardNumber);
        sysUserMapper.update(sysUser);

        String ltId = sysUser.getLtId();

        return true;
    }

    @Override
    public boolean accountIsRoot(String account) {
        //查询用户信息
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.select(SYS_USER.ID);
        wrapper.from(SysUser.class);
        wrapper.where(SYS_USER.EMAIL.eq(account).or(SYS_USER.PHONE.eq(account)).or(SYS_USER.ACCOUNT.eq(account)));
        SysUser userInfo = sysUserMapper.selectOneByQuery(wrapper);
        if (userInfo == null) return false;

        //查是该账号是否具备ROOT角色
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("user_id", userInfo.getId());
        queryWrapper.eq("role_id", 1);
        SysUserRole rootRole = userRoleMapper.selectOneByQuery(queryWrapper);
        return rootRole != null;
    }
}
